package;
import flash.display.MovieClip;
import flash.events.AsyncErrorEvent;
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.net.NetConnection;
import flash.net.Responder;
import flash.Lib;
import Player;
import Bullet;

class Game extends MovieClip
{
	var username : String;
	var nc : NetConnection;
	var log : Dynamic;
	var players : Hash<Player>;
	var bullets : Hash<Bullet>;
	var player : Player;
	var bulletId:Int;
	
	public function new(nc, name, log)
	{
		super();
		this.nc = nc;
		this.username = name;
		this.log = log;
		createView();
		bulletId=0;
		nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
		nc.client = this;
		players = new Hash();
		bullets = new Hash();
		nc.call("getPlayers", new Responder(onResultGetPlayers, onError));
		nc.call("getBullets", new Responder(onResultGetBullets, onError));
	}
	function onPlayerJoin(data:PlayerData)
	{
		var p = new Player(data, data.name == player.name);
		players.set(data.name, p);
		addChild(p);
		log(data.name+" joined.");
	}
	function onBulletJoin(data:BulletData)
	{
		var control = player.name == data.name.split("-")[0];
		var b = new Bullet(data, control);
		bullets.set(data.name, b);
		addChild(b);
		if(control)
		{
			b.addEventListener("move", onBulletMove);
			b.addEventListener("leave", bulletLeave);
		}
		//log(data.name+" joined.");
	}
	function onPlayerLeave(data:PlayerData)
	{
		var p = players.get(data.name);
		if(p == player)
		{
			p.removeEventListener("move", onPlayerMove);
			p.removeEventListener("fire", onFire);
			p.cleanup();
		}
		removeChild(p);
		players.remove(data.name);
		log(data.name+" left.");
	}
	function onBulletLeave(data:BulletData)
	{
		var b = bullets.get(data.name);
		if(b!=null)
		{
			if(data.name.split("-")[0] == player.name)
			{
				b.removeEventListener("move", onBulletMove);
				b.removeEventListener("leave", bulletLeave);
				b.cleanup();
			}
			removeChild(b);
		}
		if(bullets.exists(data.name))
			bullets.remove(data.name);
		//log(data.name+" left.");
	}
	function onHit(b:BulletData, p:PlayerData):Void
	{
		var owner = b.name.split("-")[0];
		log(p.name +" got hit by " + owner+ " ! ! ! ");
		if(owner == username)
		{
			var bullet = bullets.get(b.name);
			if(bullet!=null)
				bullet.dispatchEvent(new Event("leave"));
		}
	}
	function onPlayerMove(event:Event)
	{
		nc.call("playerMove", new Responder(null, onError), event.target.data);
	}
	function onBulletMove(event:Event)
	{
		nc.call("bulletMove", new Responder(null, onError), event.target.data);
	}
	function bulletLeave(event:Event)
	{
		nc.call("bulletLeave", new Responder(null, onError), event.target.data);
		players.get(event.target.data.name.split("-")[0]).fireEnabled = true;
	}
	function updatePlayer(data:PlayerData)
	{
		players.get(data.name).setData(data);
	}
	function updateBullet(data:BulletData)
	{
		if(bullets.exists(data.name) && bullets.get(data.name)!=null)
			bullets.get(data.name).setData(data);
		else
			bullets.remove(data.name);
	}
	function onResultGetPlayers(data:Array<PlayerData>)
	{
		for(d in data)
		{
			if(!players.exists(d.name))
			{
				var p = new Player(d, d.name==username);
				if(player==null && d.name==username)
				{
					player = p;
					player.addEventListener("move", onPlayerMove);
					player.addEventListener("fire", onFire);
					
				}
				addChild(p);
				players.set(d.name, p);
			}
		}
	}
	function onResultGetBullets(data:Array<BulletData>)
	{
		for(b in data)
		{
			if(!bullets.exists(b.name))
			{
				var b = new Bullet(b, false);
				addChild(b);
				bullets.set(b.name, b);
			}
		}
	}
	function onFire(event:Event)
	{
		var bulletData = Reflect.copy(event.target.data);
		bulletData.name = event.target.data.name+"-" + bulletId++;
		nc.call("fire", new Responder(null, onError), bulletData);
	}
	function onNetStatus(event:NetStatusEvent):Void
	{
		log("code:"+event.info.code);
		log("description:"+event.info.description);
	}
	function onAsyncError(event:AsyncErrorEvent):Void
	{
		log("text:"+event.text);
		log("error:"+event.error);
	}
	function onError(obj)
	{
		log("Game onError");
		log(obj.level);
		log(obj.code);
		log(obj.description);
	}
	function createView()
	{
		this.graphics.lineStyle(0,1);
		this.graphics.drawRect(0,0,800,600);
	}
}